from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from .models import UserProfile
from django.utils.safestring import mark_safe
from django.conf import settings
import os
import hashlib
import urllib.request
import urllib.parse
import json


class UserProfileInline(admin.StackedInline):
    """在Django认证用户界面内联显示用户完整信息"""
    model = UserProfile
    can_delete = False
    verbose_name_plural = '用户完整信息'
    fields = ('user_profile_id', 'nickname', 'phone', 'display_avatar', 'avatar', 'points', 'bio',
              'lat', 'lng', 'city', 'province', 'nation', 'location_updated_at')
    readonly_fields = ('user_profile_id', 'display_avatar', 'location_updated_at')
    
    def user_profile_id(self, obj):
        """显示用户ID"""
        return obj.user.id
    user_profile_id.short_description = '用户ID'
    
    def display_avatar(self, obj):
        """显示头像预览"""
        if obj.avatar:
            html = f'<img src="{obj.avatar}" alt="用户头像" style="width: 80px; height: 80px; border-radius: 50%; object-fit: cover; border: 2px solid #007bff;">'
            return mark_safe(html)
        else:
            html = '<div style="width: 80px; height: 80px; border-radius: 50%; background: #f0f0f0; display: flex; align-items: center; justify-content: center; color: #999;">暂无头像</div>'
            return mark_safe(html)
    display_avatar.short_description = '头像预览'


class CustomUserAdmin(UserAdmin):
    """Django认证用户管理界面 - 显示完整用户信息"""
    inlines = (UserProfileInline,)
    
    # 重新定义用户列表显示的字段，按要求的顺序显示
    list_display = ('id', 'get_avatar', 'username', 'get_nickname', 'get_phone', 'email', 'get_points', 'get_city', 'get_province')
    list_filter = ('is_active', 'is_staff', 'is_superuser', 'date_joined', 'last_login', 'profile__city', 'profile__province')
    search_fields = ('username', 'email', 'profile__nickname', 'profile__phone', 'profile__city', 'profile__province')
    date_hierarchy = 'date_joined'
    actions = ['action_reverse_geocode_profile', 'action_clear_profile_location']
    
    def get_avatar(self, obj):
        """获取用户头像 - 显示为图片"""
        try:
            if obj.profile.avatar:
                # 返回HTML格式的图片，使用mark_safe标记为安全
                html = f'<img src="{obj.profile.avatar}" alt="用户头像" style="width: 50px; height: 50px; border-radius: 50%; object-fit: cover; border: 2px solid #007bff;">'
                return mark_safe(html)
            else:
                html = '<div style="width: 50px; height: 50px; border-radius: 50%; background: #f0f0f0; display: flex; align-items: center; justify-content: center; color: #999; font-size: 12px;">无头像</div>'
                return mark_safe(html)
        except UserProfile.DoesNotExist:
            html = '<div style="width: 50px; height: 50px; border-radius: 50%; background: #f0f0f0; display: flex; align-items: center; justify-content: center; color: #999; font-size: 12px;">无头像</div>'
            return mark_safe(html)
    get_avatar.short_description = '头像'
    
    def get_nickname(self, obj):
        """获取用户昵称"""
        try:
            return obj.profile.nickname or "未设置"
        except UserProfile.DoesNotExist:
            return "未设置"
    get_nickname.short_description = '昵称'
    
    def get_phone(self, obj):
        """获取用户电话"""
        try:
            return obj.profile.phone or "未设置"
        except UserProfile.DoesNotExist:
            return "未设置"
    get_phone.short_description = '电话'
    
    def get_points(self, obj):
        """获取用户积分"""
        try:
            return obj.profile.points
        except UserProfile.DoesNotExist:
            return 0
    get_points.short_description = '积分'
    
    def get_bio(self, obj):
        """获取用户个人简介"""
        try:
            return obj.profile.bio or "未设置"
        except UserProfile.DoesNotExist:
            return "未设置"
    get_bio.short_description = '个人简介'

    def get_city(self, obj):
        try:
            return obj.profile.city or '未知'
        except UserProfile.DoesNotExist:
            return '未知'
    get_city.short_description = '城市'

    def get_province(self, obj):
        try:
            return obj.profile.province or '未知'
        except UserProfile.DoesNotExist:
            return '未知'
    get_province.short_description = '省份'

    def _http_get(self, url, params):
        query = urllib.parse.urlencode(params)
        full = url + ('?' + query if query else '')
        with urllib.request.urlopen(full, timeout=5) as resp:
            body = resp.read().decode('utf-8')
            return json.loads(body)

    def _build_sig(self, path: str, params: dict, sk: str) -> str:
        items = sorted([(k, v) for k, v in params.items() if k != 'sig'], key=lambda x: x[0])
        query = urllib.parse.urlencode(items)
        raw = f"{path}?{query}{sk}"
        return hashlib.md5(raw.encode('utf-8')).hexdigest()

    def action_reverse_geocode_profile(self, request, queryset):
        key = getattr(settings, 'TENCENT_MAP_KEY', '') or os.environ.get('TENCENT_MAP_KEY', '')
        success = 0
        failed = 0
        if not key:
            self.message_user(request, '未配置腾讯位置服务Key', level='error')
            return
        for user in queryset:
            try:
                profile = getattr(user, 'profile', None)
                if not profile or profile.lat is None or profile.lng is None:
                    failed += 1
                    continue
                params = {'location': f"{profile.lat},{profile.lng}", 'key': key, 'radius': 1000}
                sig_secret = os.environ.get('TENCENT_MAP_SIG_SECRET', '')
                if sig_secret:
                    params['sig'] = self._build_sig('/ws/geocoder/v1', params, sig_secret)
                data = self._http_get('https://apis.map.qq.com/ws/geocoder/v1/', params)
                if int(data.get('status', -1)) != 0:
                    failed += 1
                    continue
                ad = (data.get('result', {}) or {}).get('ad_info', {})
                profile.city = ad.get('city') or profile.city
                profile.province = ad.get('province') or profile.province
                profile.nation = ad.get('nation') or profile.nation
                profile.save(update_fields=['city','province','nation'])
                success += 1
            except Exception:
                failed += 1
        self.message_user(request, f'用户位置填充完成：成功 {success} 条，失败 {failed} 条')
    action_reverse_geocode_profile.short_description = '逆地理填充用户位置（选中项）'

    def action_clear_profile_location(self, request, queryset):
        for user in queryset:
            profile = getattr(user, 'profile', None)
            if profile:
                profile.city = None
                profile.province = None
                profile.nation = None
                profile.lat = None
                profile.lng = None
                profile.save(update_fields=['city','province','nation','lat','lng'])
        self.message_user(request, f'已清除 {queryset.count()} 个用户位置数据')
    action_clear_profile_location.short_description = '清除用户位置数据（选中项）'


# 确保用户模型正确注册到Django认证系统中
# 先取消注册所有可能冲突的注册
try:
    admin.site.unregister(User)
except admin.sites.NotRegistered:
    pass

# 重新注册用户管理
admin.site.register(User, CustomUserAdmin)

# 确保UserProfile模型不会单独显示在管理员界面
# 不要注册UserProfile模型，让它通过内联方式显示

